<template>
    <el-upload
      ref="upload"
      :accept="upload.exts"
      action
      :http-request="handleUpload"
      :auto-upload="true"
      :before-upload="handleBeforeUpload"
      :data="upload.data"
      :disabled="disabled"
      :file-list="upload.fileList"
      :headers="upload.headers"
      :limit="upload.limit"
      :on-error="handleFileError"
      :on-preview="handleFilePreview"
      :on-progress="handleFileUploadProgress"
      :on-remove="handleFileRemove"
      :on-success="handleFileSuccess"
    >
      <el-button slot="trigger" :class="hidden ? 'hidden' : ''" :disabled="disabled" :size="size">
        <i class="el-icon-upload2"></i>
        <span class="upload-btn-text">上 传</span>
      </el-button>
      <el-progress v-if="showProgress" :percentage="percentage" :format="format"></el-progress>
    </el-upload>
</template>

<script>
import { getToken } from '@/utils/auth'
import * as oss from './oss'
import emitter from 'element-ui/src/mixins/emitter'
import { saveOssFile, deleteOssFile, listByBusinessKeyAndUploaderId } from './oss'

export default {
  name: 'AttachmentOSS',
  mixins: [emitter],
  model: {
    prop: 'uploadValue',
    event: 'change'
  },
  props: {
    disabled: {
      required: false,
      type: Boolean,
      default: false
    },
    size: {
      required: false,
      type: String,
      default: 'small'
    },
    accept: {
      required: false,
      type: String
    },
    businessId: {
      required: false,
      type: Number
    },
    uploaderId: {
      required: true,
      type: String
    },
    onFileSuccess: {
      required: false,
      type: Function
    },
    uploadSizeLimit: {
      required: false,
      type: Number,
      default: 10
    },
    limit: {
      required: false,
      type: Number,
      default: 10
    },
    hidden: {
      type: Boolean,
      default: false
    },
    uploadValue: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      //上传的附件ID拼接的字符串，新增时使用
      uploadAttachmentIds: '',
      // 上传参数
      upload: {
        // 是否禁用上传
        isUploading: false,
        // 设置上传的请求头部
        headers: { Authorization: 'Bearer ' + getToken() },
        // 上传的文件列表
        fileList: [],
        // 接受的格式
        exts: '.jpg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt',
        // 上传附带的数据
        data: {
          uploaderId: this.uploaderId,
          businessKey: this.businessId
        },
        limit: this.limit
      },
      // 展示进度条
      showProgress: false,
      // 进度条进度
      percentage: 0,
    }
  },
  created() {
    //重置接收文件格式
    if (this.accept) {
      this.upload.exts = this.accept
    }
  },
  methods: {
    // 处理上传动作
    handleUpload(file) {
      const _this = this;
      oss.doClient(function (client) {
        // 重命名文件（时间戳+随机四位数字）防止重复文件
        let uidFile = new Date().getTime() + Math.floor(Math.random()*(9999-1000))+1000;
        let suffix = file.file.name.split('.')[1];
        // client.multipartUpload('文件路径/文件名称','上传文件')
        let ossFilePath = `attachment/common/${uidFile}.${suffix}`;
        client.multipartUpload(ossFilePath, file.file, {
          progress: function (p) {
            //p进度条的值
            _this.showProgress = true;
            _this.percentage = Math.floor(p * 100);
          }
        }).then(result => {

          // 隐藏进度条
          _this.showProgress = false;
          _this.percentage = 0;

          let ossFile = {
            uploaderId: _this.uploaderId,
            businessKey: _this.businessId ? _this.businessId : '',
            fileName: file.file.name,
            fileSize: file.file.size,
            fileOssLink: ossFilePath,
            fileSuffix: suffix,
          }
          saveOssFile(ossFile).then(res => {

            // 由于action为空 此处调用上传成功接口
            if (res.code === 200) {
              _this.upload.isUploading = false

              if (_this.uploadAttachmentIds) {
                _this.uploadAttachmentIds += ',' + res.data.id
              } else {
                _this.uploadAttachmentIds = res.data.id
              }

              _this.upload.fileList = [];
              //处理文件队列里面url的基础路径
              _this.upload.fileList.push({
                status: 'success',
                name: res.data.fileName,
                size: res.data.size,
                percentage: 100,
                response: {
                  attachmentId: res.data.id,
                  fileName: res.data.fileName,
                  url: res.data.fileOssLink,
                  ossPath: res.data.fileOssLink
                }
              });

              _this.dispatchParentValidate()

              _this.$emit('onFileSuccess', _this.uploadAttachmentIds)

              //上传成功返回值
              _this.$message({
                message: '文件上传成功',
                type: 'success'
              });

            } else {
              _this.msgError(res.msg)
            }
          });

        }).catch(err => {
          _this.$message.error('上传失败，请重试。');
          _this.showProgress = false;
          _this.percentage = 0;
          console.err("err:", err);
        });
      })
    },
    /**初始化文件队列*/
    initFileList() {
      if (this.businessId && this.uploaderId) {
        listByBusinessKeyAndUploaderId(this.businessId, this.uploaderId).then(response => {
          this.upload.fileList = response.map(element => {
            return {
              status: 'success',
              name: element.fileName,
              size: element.size,
              percentage: 100,
              response: {
                attachmentId: element.id,
                fileName: element.fileName,
                url: element.fileOssLink
              }
            }
          })

          //如果首次进入，没有文件，不触发验证
          if (this.upload && this.upload.fileList && this.upload.fileList.length > 0) {
            this.dispatchParentValidate()
          }
        })
      }
    },
    // 文件上传前处理
    handleBeforeUpload(file) {
      const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)
      if (this.accept && this.accept.indexOf(fileSuffix) === -1) {
        this.$message({
          type: 'error',
          message: '上传文件只能是' + this.accept + '格式'
        })
        return false
      }

      // 上传大小检查，以M为单位
      const uploadSizeLimit = this.uploadSizeLimit * 1024 * 1024
      if (!file || file && file.size > uploadSizeLimit) {
        this.msgError('上传文件大小不能大于' + this.uploadSizeLimit + 'M')
        return false
      }
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true
    },
    // 文件上传成功处理 action为空 上传成功的回调方法失效
    handleFileSuccess(response) {

    },
    //文件上传失败
    handleFileError(err, file, fileList) {
      this.msgError('上传错误')
    },
    // 文件删除处理
    handleFileRemove(file, fileList) {
      const _this = this;
      if (file && file.response) {
        let fileOssPath = file.response.url;
        let attachmentId = parseInt(file.response.attachmentId)

        oss.doClient(function(client) {
          client.delete(fileOssPath).then(result => {
            deleteOssFile(attachmentId).then(response => {
              _this.upload.fileList = fileList;

              _this.dispatchParentValidate();

              _this.uploadAttachmentIds = String(_this.uploadAttachmentIds).replace(','+attachmentId, '').replace(attachmentId, '');
              _this.$emit('onFileRemove', attachmentId);
              _this.msgSuccess(response.msg)
            })
          }).catch(error => {
            console.error(error);
          });
        })
      }
    },
    //文件预览
    handleFilePreview(file) {
      if (file && file.response) {
        oss.doClient(function(client) {
          let fileOssPath = file.response.url;
          let url = client.signatureUrl(fileOssPath);
          window.open(url)
        })

      }
    },
    //清空队列
    clearFiles() {
      this.uploadAttachmentIds = ''
      this.$refs.upload.clearFiles()
    },
    //设置businessId
    setBusinessId(businessId) {
      this.upload.data.businessKey = businessId
    },
    //触发父组件验证
    dispatchParentValidate() {
      const fileListNotEmpty = this.upload && this.upload.fileList && this.upload.fileList.length > 0 ? 1 : undefined
      this.$emit('change', fileListNotEmpty)
      this.dispatch('ElFormItem', 'el.form.blur', [fileListNotEmpty])
    },
    // 进度条格式化
    format(percentage) {
      return percentage === 100 ? '上传完成' : `${percentage}%`;
    },
  }
}
</script>

<style scoped>
.hidden {
  display: none;
}
</style>
